<!doctype html>
<html lang="en">

<head>
    <meta charset="utf-8">
    <title>简易ps工具</title>
    <link rel="stylesheet" href="../storeHouse/bootstrap/3.3.7/css/bootstrap.min.css">
    <link rel="stylesheet" href="../src/demo.css">
</head>
<body>
    <div id="status" class="alert alert-primary" role="alert">Loading OpenCV...</div>
    <div id="container">
        <header>
            <h2 style="text-align: center;">简易ps工具</h2>
        </header>
        <hr>
        <div style="width: 450px; display: inline-block;">
            <h4 style="text-align: center;">imageSrc</h4>
        </div>
        <div style="width: 450px; display: inline-block;">
            <h4 style="text-align: center;">canvasOutput</h4>
        </div>
        <div style="width: 540px; display: inline-block;">
            <h4 style="text-align: center;margin-left: 120px;">图像处理</h4>
        </div>
        <div style="background-color:gray; width: 900px;height: 450px;float: left;">
            <img id="imageSrc" alt="No Image" class="small" src="../banner/april-9.jpg"
                style="width: 450px; height: 450px;margin-left: -2px;">
            <canvas id="canvasOutput" class="small" height="300px" style="width: 450px;height: 450px;margin-left: 0px;">
            </canvas>
        </div>
        <div style="background-color: ghostwhite;width: 100px;height: 450px;;margin-left: 890px;">
            <ul class="nav nav-pills" id="menu">
                <li role="presentation" class="active" id="transForm"><a href="#">几何变换</a></li>
                <li role="presentation" id="Gray"><a href="#">灰度化</a></li>
                <li role="presentation" id="Canny"><a href="#">边缘检测</a></li>
                <li role="presentation" id="AdaptiveThreshold"><a href="#">阈值处理</a></li>
                <li role="presentation" id="SmoothingImages"><a href="#">平滑处理</a></li>
                <li role="presentation" id="Morphological"><a href="#">形态学</a></li>
                <li role="presentation" id="HoughLineTransform"><a href="#">线变换</a></li>
                <li role="presentation" id="Histograms"><a href="#">直方图</a></li>
                <li role="presentation" id="GrabCut"><a href="#">前景提取</a></li>
                <li role="presentation" id="Watershed"><a href="#">图像分割</a></li>
                <li role="presentation" id="Contours"><a href="#">图像轮廓</a></li>

            </ul>
        </div>
        <div style="position: absolute;top:100px;right:100px">
            <ul class="nav nav-pills" id="menu">
                <li><button type="button" class="chooseR">
                        <P style="position: absolute;margin-left: 10px;">选择图片</P>
                        <input id="fileInput" type="file" style="opacity:0; width: 80px;position: relative;"></input>
                    </button></li>
                <li><button type="button" class="chooseR" id="reTurn">上一步操作</button></li>
                <li><button type="button" class="chooseR" onclick="download()">保存图片</button></li>
            </ul>
        </div>

        <div id="down"
            style="width: 310px;height: 450px;background-color:rosybrown;position: absolute;top: 205px;right: 100px;display: none;">
            <div style="width: 400px;height: 200px;">
                <button type="button" class="chooseR" id="transFormLeft">向左旋转</button>
                <button type="button" class="chooseR" id="transFormRight">向右旋转</button>
                <button type="button" class="chooseR" id="GetaiffneTrans">仿射变换</button>
                <button type="button" class="chooseR" id="warpTrans">透视转换</button>
            </div>
        </div>
        <div id="down1"
            style="width: 310px;height: 450px;background-color:rosybrown;position: absolute;top: 205px;right: 100px;display: none;">
            <div style="width: 400px;height: 200px;">
                <button type="button" class="chooseR" id="Convolution">2D卷积</button>
                <button type="button" class="chooseR" id="Averaging">平均</button>
                <button type="button" class="chooseR" id="GaussianBlurring">高斯模糊</button>
                <button type="button" class="chooseR" id="MedianBlurring">中值模糊</button>
            </div>
        </div>
        <div id="down2"
            style="width: 310px;height: 450px;background-color:rosybrown;position: absolute;top: 205px;right: 100px;display: none;">
            <div style="width: 400px;height: 200px;">
                <button type="button" class="chooseR" id="Erosion">侵蚀</button>
                <button type="button" class="chooseR" id="Dilation">扩张</button>
                <button type="button" class="chooseR" id="Gradient">形态梯度</button>
                <button type="button" class="chooseR" id="Structuring">结构化</button>
            </div>
        </div>
        <div id="down3"
            style="width: 310px;height: 450px;background-color:rosybrown;position: absolute;top: 205px;right: 100px;display: none;">
            <div style="width: 400px;height: 200px;">
                <button type="button" class="chooseR" id="HoughLines">直线检测</button>
                <button type="button" class="chooseR" id="HoughLinesP">概率霍夫变换</button>
            </div>
        </div>

        <div id="down4"
            style="width: 310px;height: 450px;background-color:rosybrown;position: absolute;top: 205px;right: 100px;display: none;">
            <div>
                <span>
                    <h4>是否保存当前canvas进行下一步操作？</h4>
                </span>
                <button type="button" class="chooseR" id="baoCun">保存</button>

            </div>
            <div style="width: 310px;height: 200px;margin-top: 170px;background-color: ghostwhite;">
                <span style="text-align: center;">
                    <h4>属性</h4>
                </span>
                <div><input type='range' name="trackbar" id='trackbar' value='50' min='0' max='100' step='1' oninput=''
                        style="width: 200px;"><label for="trackbar">阈值1:<span id="threshold1"></span></label></div>
                <input type='range' id='trackbar1' value='50' min='0' max='100' step='1' oninput=''
                    style="width: 200px;"><label>阈值2:<span id="threshold2"></span></label>
            </div>
        </div>
        <div id="down5"
            style="width: 310px;height: 450px;background-color:rosybrown;position: absolute;top: 205px;right: 100px;display: none;">
            <div><span>
                    <h4>是否保存当前canvas进行下一步操作？</h4>
                </span>
                <button type="button" class="chooseR" id="baoCun1">保存</button>
            </div>
            <div style="width: 310px;height: 200px;margin-top: 170px;background-color: ghostwhite;">

                <span style="text-align: center;">
                    <h4>属性</h4>
                </span>
                <div><input type='range' name="trackbar" id='trackbar2' value='100' min='0' max='200' step='1'
                        oninput='' style="width: 200px;"><label for="trackbar">阈值:<span id="threshold"></span></label>
                </div>
            </div>
        </div>
    </div>
    <hr>
    <footer style="margin-top: -10px;">
        <h5 style="text-align: center;color: gray;">@author 202103021294 姚钧文 计算机视觉课程设计</h5>
    </footer>
    <script src="../src/script.js"></script>
    <script src="../storeHouse/jquery/jquery-2.1.4.min.js"></script>
    <script src="../storeHouse/bootstrap/3.3.7/js/bootstrap.min.js"></script>
    <!-- OpenCV.js 4.5.5 版本 -->
    <script async="" src='https://docs.opencv.org/4.5.5/opencv.js' type="text/javascript" onload="onOpenCvReady();"
        onerror="onOpenCvError();"></script>
    <script type="text/javascript">
        let imgElement = document.getElementById("imageSrc")
        let canvas = document.getElementById("canvasOutput")
        var context = canvas.getContext('2d');
        var img = new Image()
        img.src = imgElement.src
        let arrImg = []
        arrImg.push(img.src)
        let saveCanvas = function () {//每次canvas 操作会清除之前图像，防止垃圾回收保存之前图像
            let imageDataUrl = canvas.toDataURL('image/png');
            img.src = imageDataUrl
            arrImg.push(imageDataUrl)
        }
        let cleanCanvas = function () {
            var w = canvas.width;
            var h = canvas.height;
            context.clearRect(0, 0, w, h);
        }
        $(function () {
            $(".chooseT").mouseover(function () {
                $(this)[0].style = "background-color:gray"
            })
            $(".chooseT").mouseout(function () {
                $(this)[0].style = "background-color:white"
            })
            $(".chooseR").mouseover(function () {
                $(this)[0].style = "background-color:gray"
            })
            $(".chooseR").mouseout(function () {
                $(this)[0].style = "background-color:ghostwhite"
            })
            $("#menu li").mouseover(function () {
                $(this).siblings().removeClass("active")
                $(this).addClass("active")
            })
            $("#menu li").mouseout(function () {
                $(this).siblings().removeClass("active")
            })
            $("#transForm").click(function () {
                $("#down")[0].style.display = "block"
                $("#down1")[0].style.display = "none"
                $("#down2")[0].style.display = "none"
                $("#down3")[0].style.display = "none"
                $("#down4")[0].style.display = "none"
                $("#down5")[0].style.display = "none"
            })
            $("#SmoothingImages").click(function () {
                $("#down1")[0].style.display = "block"
                $("#down")[0].style.display = "none"
                $("#down2")[0].style.display = "none"
                $("#down3")[0].style.display = "none"
                $("#down4")[0].style.display = "none"
                $("#down5")[0].style.display = "none"
            })
            $("#Morphological").click(function () {
                $("#down2")[0].style.display = "block"
                $("#down")[0].style.display = "none"
                $("#down1")[0].style.display = "none"
                $("#down3")[0].style.display = "none"
                $("#down4")[0].style.display = "none"
                $("#down5")[0].style.display = "none"
            })
            $("#HoughLineTransform").click(function () {
                $("#down3")[0].style.display = "block"
                $("#down")[0].style.display = "none"
                $("#down1")[0].style.display = "none"
                $("#down2")[0].style.display = "none"
                $("#down4")[0].style.display = "none"
                $("#down5")[0].style.display = "none"
            })
            $("#Canny").click(function () {
                $("#down4")[0].style.display = "block"
                $("#down")[0].style.display = "none"
                $("#down1")[0].style.display = "none"
                $("#down2")[0].style.display = "none"
                $("#down3")[0].style.display = "none"
                $("#down5")[0].style.display = "none"
            })
            $("#AdaptiveThreshold").click(function () {
                $("#down5")[0].style.display = "block"
                $("#down")[0].style.display = "none"
                $("#down1")[0].style.display = "none"
                $("#down2")[0].style.display = "none"
                $("#down3")[0].style.display = "none"
                $("#down4")[0].style.display = "none"
            })
            $("#fileInput").change(
                (e) => {
                    imgElement.src = URL.createObjectURL(e.target.files[0]);
                    img.src = imgElement.src
                }
            )
            $("#reTurn").click(function () {
                console.log("当前数组长度" + arrImg.length)
                console.log("未处理前数组元素" + arrImg)
                arrImg.pop()
                if (arrImg.length > 1) {
                    img.src = arrImg[arrImg.length - 1]
                    console.log(typeof (img.src))
                    let mat = cv.imread(img);
                    cv.imshow('canvasOutput', mat);
                    mat.delete();
                }
                else if (arrImg.length <= 1) {
                    img.src = imgElement.src
                    let mat = cv.imread(img);
                    cv.imshow('canvasOutput', mat);
                    mat.delete();
                }
                console.log("当前数组元素" + arrImg)
                // cleanCanvas()

            })
            $("#Gray").click(function () {//图像灰度化
                console.log("灰度化")
                let mat = cv.imread(img);
                cv.cvtColor(mat, mat, cv.COLOR_BGR2GRAY);
                cv.imshow('canvasOutput', mat);
                saveCanvas()
                console.log(img.width, img.height)
                mat.delete();
            })
            $("#Canny").click(function () {//边缘检测 
                let threshold1 = 50//阈值1_边缘检测
                let threshold2 = 50//阈值2_边缘检测 
                let trackbar = document.getElementById('trackbar');
                let trackbar1 = document.getElementById('trackbar1');
                trackbar.value = 50
                trackbar1.value = 50
                $("#threshold1")[0].innerHTML = threshold1
                $("#threshold2")[0].innerHTML = threshold2
                let src = cv.imread(img);
                let dst = new cv.Mat();
                cv.cvtColor(src, src, cv.COLOR_RGB2GRAY, 0);
                cv.Canny(src, dst, threshold1, threshold2, 3, false);
                cv.imshow('canvasOutput', dst);
                // saveCanvas()
                src.delete(); dst.delete();
                $("#trackbar").change(function () {

                    threshold1 = parseInt(trackbar.value)//阈值1
                    let src = cv.imread(img);
                    let dst = new cv.Mat();
                    cv.cvtColor(src, src, cv.COLOR_RGB2GRAY, 0);
                    cv.Canny(src, dst, threshold1, threshold2, 3, false);
                    cv.imshow('canvasOutput', dst);
                    $("#threshold1")[0].innerHTML = threshold1
                    console.log(threshold1, threshold2)

                })
                $("#trackbar1").change(function () {

                    threshold2 = parseInt(trackbar1.value)//阈值2
                    let src = cv.imread(img);
                    let dst = new cv.Mat();
                    cv.cvtColor(src, src, cv.COLOR_RGB2GRAY, 0);
                    cv.Canny(src, dst, threshold1, threshold2, 3, false);
                    cv.imshow('canvasOutput', dst);
                    $("#threshold2")[0].innerHTML = threshold2
                    console.log(threshold1, threshold2)
                })
                $("#baoCun").click(function () {
                    saveCanvas()
                })
            })
            $("#AdaptiveThreshold").click(function () {//阈值处理
                console.log("阈值处理")
                let threshold = 100//阈值
                let trackbar = document.getElementById('trackbar2');
                trackbar.value = 100
                $("#threshold")[0].innerHTML = threshold
                let src = cv.imread(img);
                let dst = new cv.Mat();
                cv.cvtColor(src, src, cv.COLOR_RGBA2GRAY, 0);
                cv.adaptiveThreshold(src, dst, threshold, cv.ADAPTIVE_THRESH_GAUSSIAN_C, cv.THRESH_BINARY, 3, 2);
                cv.imshow('canvasOutput', dst);
                src.delete();
                dst.delete();
                $("#trackbar2").change(function () {
                    threshold = parseInt(trackbar.value)//阈值
                    $("#threshold")[0].innerHTML = threshold
                    console.log(threshold)
                    let src = cv.imread(img);
                    let dst = new cv.Mat();
                    cv.cvtColor(src, src, cv.COLOR_RGBA2GRAY, 0);
                    cv.adaptiveThreshold(src, dst, threshold, cv.ADAPTIVE_THRESH_GAUSSIAN_C, cv.THRESH_BINARY, 3, 2);
                    cv.imshow('canvasOutput', dst);
                    src.delete();
                    dst.delete();
                })
                $("#baoCun1").click(function () {
                    saveCanvas()
                })
            })
            $("#transFormLeft").click(function () {//向左旋转
                let src = cv.imread(img);
                let dst = new cv.Mat();
                console.log(src.rows, src.cols)
                let dsize = new cv.Size();
                let center = new cv.Point(src.cols / 2, src.rows / 2);
                let M = cv.getRotationMatrix2D(center, 90, 1);
                cv.warpAffine(src, dst, M, dsize, cv.INTER_LINEAR, cv.BORDER_CONSTANT, new cv.Scalar());
                cv.imshow('canvasOutput', dst);
                saveCanvas()
                console.log(dsize)
                src.delete(); dst.delete(); M.delete();
            })
            $("#transFormRight").click(function () {//向右旋转
                let src = cv.imread(img);
                let dst = new cv.Mat();
                console.log(src.rows, src.cols);
                let dsize = new cv.Size();
                let center = new cv.Point(src.cols / 2, src.rows / 2);
                let M = cv.getRotationMatrix2D(center, -90, 1);
                cv.warpAffine(src, dst, M, dsize, cv.INTER_LINEAR, cv.BORDER_CONSTANT, new cv.Scalar());
                cv.imshow('canvasOutput', dst);
                saveCanvas()
                src.delete(); dst.delete(); M.delete();
            })
            $("#GetaiffneTrans").click(function () {//仿射变换
                let src = cv.imread(img);
                let dst = new cv.Mat();
                let srcTri = cv.matFromArray(3, 1, cv.CV_32FC2, [0, 0, 0, 1, 1, 0]);
                let dstTri = cv.matFromArray(3, 1, cv.CV_32FC2, [0.6, 0.2, 0.1, 1.3, 1.5, 0.3]);
                let dsize = new cv.Size();
                let M = cv.getAffineTransform(srcTri, dstTri);
                cv.warpAffine(src, dst, M, dsize, cv.INTER_LINEAR, cv.BORDER_CONSTANT, new cv.Scalar());
                cv.imshow('canvasOutput', dst);
                saveCanvas()
                src.delete(); dst.delete(); M.delete(); srcTri.delete(); dstTri.delete();
            })
            $("#warpTrans").click(function () {//透视变化
                let src = cv.imread(img);
                let dst = new cv.Mat();
                let dsize = new cv.Size();
                let srcTri = cv.matFromArray(4, 1, cv.CV_32FC2, [56, 65, 368, 52, 28, 387, 389, 390]);
                let dstTri = cv.matFromArray(4, 1, cv.CV_32FC2, [0, 0, 300, 0, 0, 300, 300, 300]);
                let M = cv.getPerspectiveTransform(srcTri, dstTri);
                cv.warpPerspective(src, dst, M, dsize, cv.INTER_LINEAR, cv.BORDER_CONSTANT, new cv.Scalar());
                cv.imshow('canvasOutput', dst);
                saveCanvas()
                src.delete(); dst.delete(); M.delete(); srcTri.delete(); dstTri.delete();
            })
            $("#Convolution").click(function () {//2D卷积
                let src = cv.imread(img);
                let dst = new cv.Mat();
                let M = cv.Mat.eye(3, 3, cv.CV_32FC1);
                let anchor = new cv.Point(-1, -1);
                cv.filter2D(src, dst, cv.CV_8U, M, anchor, 0, cv.BORDER_DEFAULT);
                cv.imshow('canvasOutput', dst);
                saveCanvas()
                src.delete(); dst.delete(); M.delete();
            })
            $("#Averaging").click(function () {//平均
                let src = cv.imread(img);
                let dst = new cv.Mat();
                let ksize = new cv.Size(3, 3);
                let anchor = new cv.Point(-1, -1);
                cv.blur(src, dst, ksize, anchor, cv.BORDER_DEFAULT);
                cv.imshow('canvasOutput', dst);
                saveCanvas()
                src.delete(); dst.delete();
            })
            $("#GaussianBlurring").click(function () {//高斯模糊
                let src = cv.imread(img);
                let dst = new cv.Mat();
                let ksize = new cv.Size(3, 3);
                cv.GaussianBlur(src, dst, ksize, 0, 0, cv.BORDER_DEFAULT);
                cv.imshow('canvasOutput', dst);
                saveCanvas()
                src.delete(); dst.delete();
            })
            $("#MedianBlurring").click(function () {//中值模糊
                let src = cv.imread(img);
                let dst = new cv.Mat();
                cv.medianBlur(src, dst, 5);
                cv.imshow('canvasOutput', dst);
                saveCanvas()
                src.delete(); dst.delete();
            })
            $("#Histograms").click(function () {//直方图
                let src = cv.imread(img);
                cv.cvtColor(src, src, cv.COLOR_RGBA2GRAY, 0);
                let srcVec = new cv.MatVector();
                srcVec.push_back(src);
                let accumulate = false;
                let channels = [0];
                let histSize = [256];
                let ranges = [0, 255];
                let hist = new cv.Mat();
                let mask = new cv.Mat();
                let color = new cv.Scalar(255, 255, 255);
                let scale = 2;
                cv.calcHist(srcVec, channels, mask, hist, histSize, ranges, accumulate);
                let result = cv.minMaxLoc(hist, mask);
                let max = result.maxVal;
                let dst = new cv.Mat.zeros(src.rows, histSize[0] * scale,
                    cv.CV_8UC3);
                for (let i = 0; i < histSize[0]; i++) {
                    let binVal = hist.data32F[i] * src.rows / max;
                    let point1 = new cv.Point(i * scale, src.rows - 1);
                    let point2 = new cv.Point((i + 1) * scale - 1, src.rows - binVal);
                    cv.rectangle(dst, point1, point2, color, cv.FILLED);
                }
                cv.imshow('canvasOutput', dst);
                saveCanvas()
                src.delete(); dst.delete(); srcVec.delete(); mask.delete(); hist.delete();
            })
            $("#HoughLines").click(function () {//直线检测
                let src = cv.imread(img);
                let dst = cv.Mat.zeros(src.rows, src.cols, cv.CV_8UC3);
                let lines = new cv.Mat();
                cv.cvtColor(src, src, cv.COLOR_RGBA2GRAY, 0);
                cv.Canny(src, src, 50, 200, 3);
                cv.HoughLines(src, lines, 1, Math.PI / 180,
                    30, 0, 0, 0, Math.PI);
                for (let i = 0; i < lines.rows; ++i) {
                    let rho = lines.data32F[i * 2];
                    let theta = lines.data32F[i * 2 + 1];
                    let a = Math.cos(theta);
                    let b = Math.sin(theta);
                    let x0 = a * rho;
                    let y0 = b * rho;
                    let startPoint = { x: x0 - 1000 * b, y: y0 + 1000 * a };
                    let endPoint = { x: x0 + 1000 * b, y: y0 - 1000 * a };
                    cv.line(dst, startPoint, endPoint, [255, 0, 0, 255]);
                }
                cv.imshow('canvasOutput', dst);
                saveCanvas()
                src.delete(); dst.delete(); lines.delete();
            })
            $("#HoughLinesP").click(function () {//概率霍夫变换
                let src = cv.imread(img);
                let dst = cv.Mat.zeros(src.rows, src.cols, cv.CV_8UC3);
                let lines = new cv.Mat();
                let color = new cv.Scalar(255, 0, 0);
                cv.cvtColor(src, src, cv.COLOR_RGBA2GRAY, 0);
                cv.Canny(src, src, 50, 200, 3);
                cv.HoughLinesP(src, lines, 1, Math.PI / 180, 2, 0, 0);
                for (let i = 0; i < lines.rows; ++i) {
                    let startPoint = new cv.Point(lines.data32S[i * 4], lines.data32S[i * 4 + 1]);
                    let endPoint = new cv.Point(lines.data32S[i * 4 + 2], lines.data32S[i * 4 + 3]);
                    cv.line(dst, startPoint, endPoint, color);
                }
                cv.imshow('canvasOutput', dst);
                saveCanvas()
                src.delete(); dst.delete(); lines.delete();
            })
            $("#Erosion").click(function () {//图像侵蚀
                let src = cv.imread(img);
                let dst = new cv.Mat();
                let M = cv.Mat.ones(5, 5, cv.CV_8U);
                let anchor = new cv.Point(-1, -1);
                cv.erode(src, dst, M, anchor, 1, cv.BORDER_CONSTANT, cv.morphologyDefaultBorderValue());
                cv.imshow('canvasOutput', dst);
                saveCanvas()
                src.delete(); dst.delete(); M.delete();

            })
            $("#Dilation").click(function () {//图像扩张
                let src = cv.imread(img);
                let dst = new cv.Mat();
                let M = cv.Mat.ones(5, 5, cv.CV_8U);
                let anchor = new cv.Point(-1, -1);
                cv.dilate(src, dst, M, anchor, 1, cv.BORDER_CONSTANT, cv.morphologyDefaultBorderValue());
                cv.imshow('canvasOutput', dst);
                saveCanvas()
                src.delete(); dst.delete(); M.delete();
            })
            $("#Gradient").click(function () {//图像梯度
                let src = cv.imread(img);
                cv.cvtColor(src, src, cv.COLOR_RGBA2RGB);
                let dst = new cv.Mat();
                let M = cv.Mat.ones(5, 5, cv.CV_8U);
                cv.morphologyEx(src, dst, cv.MORPH_GRADIENT, M);
                cv.imshow('canvasOutput', dst);
                saveCanvas()
                src.delete(); dst.delete(); M.delete();
            })
            $("#Structuring").click(function () {//结构化
                let src = cv.imread(img);
                cv.cvtColor(src, src, cv.COLOR_RGBA2RGB);
                let dst = new cv.Mat();
                let M = new cv.Mat();
                let ksize = new cv.Size(5, 5);
                M = cv.getStructuringElement(cv.MORPH_CROSS, ksize);
                cv.morphologyEx(src, dst, cv.MORPH_GRADIENT, M);
                cv.imshow('canvasOutput', dst);
                saveCanvas()
                src.delete(); dst.delete(); M.delete();
            })
            $("#GrabCut").click(function () {//前景提取
                let src = cv.imread(img);
                cv.cvtColor(src, src, cv.COLOR_RGBA2RGB, 0);
                let mask = new cv.Mat();
                let bgdModel = new cv.Mat();
                let fgdModel = new cv.Mat();
                let rect = new cv.Rect(50, 50, 260, 280);
                cv.grabCut(src, mask, rect, bgdModel, fgdModel, 1, cv.GC_INIT_WITH_RECT);
                for (let i = 0; i < src.rows; i++) {
                    for (let j = 0; j < src.cols; j++) {
                        if (mask.ucharPtr(i, j)[0] == 0 || mask.ucharPtr(i, j)[0] == 2) {
                            src.ucharPtr(i, j)[0] = 0;
                            src.ucharPtr(i, j)[1] = 0;
                            src.ucharPtr(i, j)[2] = 0;
                        }
                    }
                }
                let color = new cv.Scalar(0, 0, 255);
                let point1 = new cv.Point(rect.x, rect.y);
                let point2 = new cv.Point(rect.x + rect.width, rect.y + rect.height);
                cv.rectangle(src, point1, point2, color);
                cv.imshow('canvasOutput', src);
                saveCanvas()
                src.delete(); mask.delete(); bgdModel.delete(); fgdModel.delete();
            })
            $("#Watershed").click(function () {//图像分割
                let src = cv.imread(img);
                let dst = new cv.Mat();
                let gray = new cv.Mat();
                let opening = new cv.Mat();
                let coinsBg = new cv.Mat();
                let coinsFg = new cv.Mat();
                let distTrans = new cv.Mat();
                let unknown = new cv.Mat();
                let markers = new cv.Mat();
                // gray and threshold image
                cv.cvtColor(src, gray, cv.COLOR_RGBA2GRAY, 0);
                cv.threshold(gray, gray, 0, 255, cv.THRESH_BINARY_INV + cv.THRESH_OTSU);
                // get background
                let M = cv.Mat.ones(3, 3, cv.CV_8U);
                cv.erode(gray, gray, M);
                cv.dilate(gray, opening, M);
                cv.dilate(opening, coinsBg, M, new cv.Point(-1, -1), 3);
                // distance transform
                cv.distanceTransform(opening, distTrans, cv.DIST_L2, 5);
                cv.normalize(distTrans, distTrans, 1, 0, cv.NORM_INF);
                // get foreground
                cv.threshold(distTrans, coinsFg, 0.7 * 1, 255, cv.THRESH_BINARY);
                coinsFg.convertTo(coinsFg, cv.CV_8U, 1, 0);
                cv.subtract(coinsBg, coinsFg, unknown);
                // get connected components markers
                cv.connectedComponents(coinsFg, markers);
                for (let i = 0; i < markers.rows; i++) {
                    for (let j = 0; j < markers.cols; j++) {
                        markers.intPtr(i, j)[0] = markers.ucharPtr(i, j)[0] + 1;
                        if (unknown.ucharPtr(i, j)[0] == 255) {
                            markers.intPtr(i, j)[0] = 0;
                        }
                    }
                }
                cv.cvtColor(src, src, cv.COLOR_RGBA2RGB, 0);
                cv.watershed(src, markers);
                // draw barriers
                for (let i = 0; i < markers.rows; i++) {
                    for (let j = 0; j < markers.cols; j++) {
                        if (markers.intPtr(i, j)[0] == -1) {
                            src.ucharPtr(i, j)[0] = 255; // R
                            src.ucharPtr(i, j)[1] = 0; // G
                            src.ucharPtr(i, j)[2] = 0; // B
                        }
                    }
                }
                cv.imshow('canvasOutput', src);
                src.delete(); dst.delete(); gray.delete(); opening.delete(); coinsBg.delete();
                coinsFg.delete(); distTrans.delete(); unknown.delete(); markers.delete(); M.delete();
                saveCanvas()

            })
            $("#Contours").click(function () {//图像轮廓
                let src = cv.imread(img);
                let dst = cv.Mat.zeros(src.rows, src.cols, cv.CV_8UC3);
                cv.cvtColor(src, src, cv.COLOR_RGBA2GRAY, 0);
                cv.threshold(src, src, 120, 200, cv.THRESH_BINARY);
                let contours = new cv.MatVector();
                let hierarchy = new cv.Mat();
                cv.findContours(src, contours, hierarchy, cv.RETR_CCOMP, cv.CHAIN_APPROX_SIMPLE);
                for (let i = 0; i < contours.size(); ++i) {
                    let color = new cv.Scalar(Math.round(Math.random() * 255), Math.round(Math.random() * 255),
                        Math.round(Math.random() * 255));
                    cv.drawContours(dst, contours, i, color, 1, cv.LINE_8, hierarchy, 100);
                }
                cv.imshow('canvasOutput', dst);
                src.delete(); dst.delete(); contours.delete(); hierarchy.delete();
                saveCanvas()
            })
        })
    </script>
</body>

</html>